<?php
declare(strict_types=1);

namespace WebApp\lib\db;

use Co;
use ErrorException;
use Exception;
use SplQueue;
use Swoole\Coroutine\PostgreSQL;

/**
 * Class MysqlPool
 * @package server\lib
 */
abstract class PostgresPool
{
    protected $db_name = '';
    /**
     * @var SplQueue
     */
    private $pool;
    public $use_co = true;

    /**
     * MysqlPool constructor.
     * @param $db_name
     */
    public function __construct($db_name)
    {
        $this->db_name = $db_name;
//        if (ServerStation::$wId === null) {
//            $this->use_co = false;
//        } else {
//            $this->use_co = true;
            $this->pool = new SplQueue;
//        }
    }

    /**
     * @return string
     */
    abstract protected function getHost(): string;

    /**
     * @return int
     */
    abstract protected function getPort(): int;

    /**
     * @return string
     */
    abstract protected function getUser(): string;

    /**
     * @return string
     */
    abstract protected function getPwd(): string;

    /**
     * @param PostgreSQL $client
     */
    private function put(PostgreSQL $client)
    {
//        $this->pool->push($client);
    }

    /**
     * @param $func
     * @param PgTable $executor
     * @return mixed
     */
    public function exec($func, PgTable $executor)
    {
        $client_is_ok = true;
        $limit_flag = isset($GLOBALS['pg_limit']);
        while ($limit_flag) {
            if ($GLOBALS['pg_limit'] <= 0){
                Co::sleep(1);
                continue;
            } else {
                $GLOBALS['pg_limit']--;
                break;
            }
        }

        $client = $this->get();
        if (!$client) {
            if($limit_flag) {
                $GLOBALS['pg_limit']++;
            }
            return false;
        }

        try {
            $res = $func($client);
            $this->put($client);
            if($limit_flag) {
                $GLOBALS['pg_limit']++;
            }
            return $res;
        }
//        catch (PDOException $e) {
//            if ($client->errno === 2006) {
//                $client_is_ok = false;
//            }
//            if ($client_is_ok) {
//                $this->put($client);
//            }
//            if($limit_flag) {
//                $GLOBALS['pg_limit']++;
//            }
//            return false;
//        }
        catch (ErrorException $e) {
            var_dump($e);
            if ($client_is_ok) {
                $this->put($client);
            }
            if($limit_flag) {
                $GLOBALS['pg_limit']++;
            }
            return false;
        } catch (Exception $e) {
            var_dump($e);
            if ($client_is_ok) {
                $this->put($client);
            }
            if($limit_flag) {
                $GLOBALS['pg_limit']++;
            }
            return false;
        } catch (\Throwable $e) {
            var_dump($e);
        }
    }

    /**
     * @return PostgreSQL
     */
    private function get()
    {
        //有空闲连接
        if (count($this->pool) > 0) {
            return $this->pool->pop();
        }

        //无空闲连接，创建新连接
        $client = new PostgreSQL();
        var_dump("host={$this->getHost()} port=5432 dbname={$this->db_name} user={$this->getUser()} password={$this->getPwd()}");
        $res = $client->connect ("host={$this->getHost()} port=5432 dbname={$this->db_name} user={$this->getUser()} password={$this->getPwd()}");

        if ($res == false) {
            return null;
        } else {
            return $client;
        }
    }
}
